import type { Next, Context } from 'koa';
import knex from '../utils/knex';

/**
 * @api {get} /role/retrieve 查询角色(分页)
 * @apiVersion 1.0.0
 * @apiDescription create by wuyanshen
 * @apiName retrieve
 * @apiGroup 角色管理
 *
 * @apiUse RequestPagingParam
 * @apiParam {String}  name 角色名称【非必填】
 * @apiParam {String}  code 角色编码【非必填】
 * @apiParam {int}     status 角色状态 (0:正常 1:停用)【非必填】
 *
 * @apiUse RequestHeader
 * @apiUse roleRetrieveSuccess
 * @apiUse RequestError
 */
async function retrieveAction(ctx: Context, next: Next) {
    const { page = 1, size = 10, name = '', code = '', status = '' } = ctx.query;
    const whereObj: Record<string, any> = {};
    if (name) {
        whereObj.name = ['like', `%${name}%`];
    }
    if (code) {
        whereObj.code = code;
    }
    if (status) {
        whereObj.status = status;
    }
    try {
        const data = await knex('sys_role')
            .where(whereObj)
            .offset(((page as number) - 1) * (size as number))
            .limit(size as number)
            .select();
        const count = await knex('sys_role').where(whereObj).count();
        ctx.success(
            {
                data,
                count: Object.values(count[0])[0],
            },
            '查询成功',
        );
    } catch (e) {
        ctx.fail(500, '查询失败  ' + e);
    }
    return next();
}

/**
 * @api {post} /role/add 新增角色
 * @apiVersion 1.0.0
 * @apiDescription create by wuyanshen
 * @apiName add
 * @apiGroup 角色管理
 *
 * @apiParam {String}  name 角色名称【必填】
 * @apiParam {String}  code 角色编码【必填】
 * @apiParam {String}  remark 备注【必填】
 * @apiParam {int}     ds_type 数据权限：1全部数据  2按明细设置  3所在公司（部门）及以下数据 4所在公司（部门）数据 5仅本人数据 【必填】
 * @apiParam {String}  ds_scope 数据范围(数据权限是2按明细设置时有值)【必填】
 * @apiParam {int}     status 角色状态 (0:正常 1:停用)【必填】
 *
 * @apiUse RequestHeader
 * @apiUse addSuccess
 * @apiUse RequestError
 */
async function addAction(ctx: Context, next: Next) {
    const { name = '', code = '', remark = '', status = '', ds_type = '', ds_scope = '' } = ctx.request.body;
    try {
        await knex('sys_role').insert({
            name,
            code,
            remark,
            status,
            ds_type,
            ds_scope,
        });
        ctx.success('', '新增成功');
    } catch (e) {
        ctx.fail(500, '新增失败  ' + e);
    }
    return next();
}

/**
 * @api {put} /role/update 修改角色
 * @apiVersion 1.0.0
 * @apiDescription create by wuyanshen
 * @apiName update
 * @apiGroup 角色管理
 *
 * @apiParam {int}     id 角色id【必填】
 * @apiParam {String}  name 角色名称【必填】
 * @apiParam {String}  code 角色编码【必填】
 * @apiParam {int}     ds_type 数据权限：1全部数据  2按明细设置  3所在公司（部门）及以下数据 4所在公司（部门）数据 5仅本人数据 【必填】
 * @apiParam {String}  ds_scope 数据范围(数据权限是2按明细设置时有值)【必填】
 * @apiParam {int}     status 角色状态 (0:正常 1:停用)【必填】
 * @apiParam {String}  remark 备注【必填】
 *
 * @apiUse RequestHeader
 * @apiUse updateSuccess
 * @apiUse RequestError
 */
async function updateAction(ctx: Context, next: Next) {
    const { id = '', name = '', code = '', remark = '', status = '', ds_type = '', ds_scope = '' } = ctx.request.body;
    try {
        await knex('sys_role').where({ id: id }).update({
            name,
            code,
            remark,
            status,
            ds_type,
            ds_scope,
        });
        ctx.success('', '修改成功');
    } catch (e) {
        ctx.fail(500, '修改失败  ' + e);
    }
    return next();
}

/**
 * @api {delete} /role/delete 删除角色
 * @apiVersion 1.0.0
 * @apiDescription create by wuyanshen
 * @apiName delete
 * @apiGroup 角色管理
 *
 * @apiParam {int} id 角色id【必填】
 *
 * @apiUse RequestHeader
 * @apiUse deleteSuccess
 * @apiUse RequestError
 */
async function deleteAction(ctx: Context, next: Next) {
    const { id = '' } = ctx.query;
    try {
        await knex('sys_role').where({ id: id }).delete();
        ctx.success('', '删除成功');
    } catch (e) {
        ctx.fail(500, '删除失败  ' + e);
    }
    return next();
}

/**
 * @api {get} /role/roleToMenuIds 角色id对应菜单id集合
 * @apiVersion 1.0.0
 * @apiDescription create by wuyanshen
 * @apiName roleToMenuIds
 * @apiGroup 角色管理
 *
 * @apiParam {int} id 角色id【必填】
 *
 * @apiUse RequestHeader
 * @apiUse roleToMenuIdsSuccess
 * @apiUse RequestError
 */
async function roleToMenuIdsAction(ctx: Context, next: Next) {
    const { id = '' } = ctx.query;
    try {
        const res = await knex('sys_role_menu').where({ role_id: id }).select();
        const menuIds = res.map((item) => item.menu_id);
        ctx.success(menuIds, '查询成功');
    } catch (e) {
        ctx.fail(500, '查询失败  ' + e);
    }
    return next();
}

/**
 * @api {post} /role/authorization 给角色授权
 * @apiVersion 1.0.0
 * @apiDescription create by wuyanshen
 * @apiName authorization
 * @apiGroup 角色管理
 *
 * @apiParam {int} id 角色id【必填】
 * @apiParam {int[]} menuIds 角色id集合【必填】
 *
 * @apiUse RequestHeader
 * @apiUse RequestSuccess
 * @apiUse RequestError
 */
async function authorizationAction(ctx: Context, next: Next) {
    const { id = '', menuIds = [] } = ctx.request.body;
    try {
        if (Array.isArray(menuIds)) {
            await knex.transaction(function (trx) {
                // 新增用户
                knex('sys_role_menu')
                    .transacting(trx)
                    .where({ role_id: id })
                    .delete()
                    .then(async () => {
                        if (menuIds.length > 0) {
                            // 新增role_menu
                            const data = menuIds.map((menuId) => {
                                return {
                                    menu_id: menuId,
                                    role_id: id,
                                };
                            });
                            await knex.batchInsert('sys_role_menu', data).transacting(trx);
                        }
                    })
                    .then(() => {
                        trx.commit();
                    })
                    .catch((err) => {
                        trx.rollback();
                        throw err;
                    });
            });
        }
        ctx.success('', '授权成功');
    } catch (e) {
        ctx.fail(500, '授权失败  ' + e);
    }
    return next();
}

/**
 * @api {get} /role/all 查询所有角色list
 * @apiVersion 1.0.0
 * @apiDescription create by wuyanshen
 * @apiName all
 * @apiGroup 角色管理
 *
 * @apiUse RequestHeader
 * @apiUse roleAllSuccess
 * @apiUse RequestError
 */
async function allAction(ctx: Context, next: Next) {
    try {
        const res = await knex('sys_role').select();
        ctx.success(res, '查询成功');
    } catch (e) {
        ctx.fail(500, '查询失败 ' + e);
    }
    return next();
}

const roleController = {
    retrieveAction,
    addAction,
    deleteAction,
    updateAction,
    allAction,
    authorizationAction,
    roleToMenuIdsAction,
};

export default roleController;
